﻿using System;
using System.Collections.Generic;
using Mozi.HttpEmbedded.Extension;

namespace Mozi.Live.RTP
{
    /// <summary>
    /// RTCP RR报文
    /// </summary>
    public class RTCPReceiverPackage:AbsRTCPPackage
    {
        /// <summary>
        /// 源标识符 同步源|贡献源
        /// </summary>
        public UInt32 Identifier { get; set; }
        /// <summary>
        /// 上报内容
        /// </summary>
        public List<RTCPReportBlock> Reports { get; set; }
        /// <summary>
        /// 扩展
        /// </summary>
        public byte[] Extension { get; set; }
        /// <summary>
        /// 包类型
        /// </summary>
        public override RTCPPackageType PackageType
        {
            get
            {
                return RTCPPackageType.ReceiverReport;
            }
            set
            {
                return;
            }
        }
        /// <summary>
        /// 打包成数据流
        /// </summary>
        /// <returns></returns>
        public override byte[] Pack()
        {
            List<byte> buffer = new List<byte>();
            buffer.AddRange(PackHeader());
            buffer.AddRange(Identifier.ToBigEndian());
            if (Reports != null)
            {
                foreach(var r  in Reports)
                {
                    buffer.AddRange(r.Pack());
                }
            }
            if (Extension != null)
            {
                buffer.AddRange(Extension);
            }
            //最后计算长度
            byte[] data = buffer.ToArray();
            Length = (ushort)(data.Length / 4 - 1);
            Array.Copy(Length.ToBigEndian(), 0, data, 2, 2);
            return data;
        }
        /// <summary>
        /// 解析数据包
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static new RTCPReceiverPackage Parse(byte[] data)
        {
            RTCPReceiverPackage pack = new RTCPReceiverPackage();
            byte[] head = new byte[4];
            Array.Copy(data, 0, head, 0, 4);
            pack.ParseHeader(head);

            pack.Identifier =data.GetBigEndianUInt32(5);
            pack.Reports = new List<RTCPReportBlock>();

            for(int i = 0; i < pack.ReportCount; i++)
            {
                byte[] reportData = new byte[20];
                Array.Copy(data, 10 + 20 * i, reportData,0, 20);
                pack.Reports.Add(RTCPReportBlock.Parse(reportData));
            }
            return pack;
        }
    }

    /// <summary>
    /// RTCP Report块
    /// </summary>
    public class RTCPReportBlock
    {
        /// <summary>
        /// 32bits
        /// </summary>
        public uint Identifier { get; set; }
        /// <summary>
        /// 8bits
        /// </summary>
        public byte FractionLost { get; set; }
        /// <summary>
        /// 24bits
        /// </summary>
        public uint PacketLost { get; set; }
        /// <summary>
        /// 32bits
        /// </summary>
        public uint ExtendedHighestSequenceNumber { get; set; }
        /// <summary>
        /// 32bits
        /// </summary>
        public uint InterArrivalJitter { get; set; }
        /// <summary>
        /// LSR 32bits 
        /// </summary>
        public uint LastReportTime { get; set; }
        /// <summary>
        /// DLSR 32bits
        /// </summary>
        public uint DelaySinceLastReport { get; set; }
        /// <summary>
        /// 解析报文
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static RTCPReportBlock Parse(byte[] data)
        {
            RTCPReportBlock pack = new RTCPReportBlock();
            pack.Identifier = data.GetBigEndianUInt32(0);
            pack.FractionLost = data[4];
            //uint24
            pack.PacketLost = data.GetBigEndianUInt32(5)>>8;
            pack.ExtendedHighestSequenceNumber = data.GetBigEndianUInt32(9);
            pack.InterArrivalJitter = data.GetBigEndianUInt32(13);
            pack.LastReportTime = data.GetBigEndianUInt32(17);
            pack.DelaySinceLastReport = data.GetBigEndianUInt32(21);
            return null;
        }
        /// <summary>
        /// 解析数据
        /// </summary>
        /// <returns></returns>
        public byte[] Pack()
        {
            List<byte> buffer = new List<byte>();
            buffer.AddRange(Identifier.ToBigEndian());
            buffer.Add(FractionLost);
            //uint24
            byte[] fraction = PacketLost.ToBigEndian();
            byte[] fraction2 = new byte[3];
            Array.Copy(fraction, fraction2, 3);
            buffer.AddRange(fraction2);
            buffer.AddRange(ExtendedHighestSequenceNumber.ToBigEndian());
            buffer.AddRange(InterArrivalJitter.ToBigEndian());
            buffer.AddRange(LastReportTime.ToBigEndian());
            buffer.AddRange(DelaySinceLastReport.ToBigEndian());
            return buffer.ToArray();
        }
    }
}
